\chapter{内置对象}

Tenon包含了一些内置的类型、变量、函数等对象，它们会在Tenon环境启动时加载，使得任何任务中的任何模块都可用。
用户自定义的类型、变量、函数等的名称不能与内置对象的名称相同。

\section{内置类型}

\subsection{intnum}

\begin{verbatim}
alias num intnum;
\end{verbatim}

用于定义中断变量和内置变量\verb|intno|. intnum类型的变量必须定义为模块变量，不能定义为函数局部变量，
也不能是const或pers变量。

\subsection{errnum}

\begin{verbatim}
alias num errnum;
\end{verbatim}

用于定义内置变量\verb|errno|.

\subsection{signaldi/signaldo/signalai/signalao/signalgi/signalgo}

这几个都是opaque类型，用于信号中断方面的功能。

\subsection{pos}

\begin{verbatim}
    record pos {
        num x;
        num y;
        num z;
    }
\end{verbatim}

pos用于表示三维坐标系中的一个点。x, y, z分别指定点在坐标系中各坐标轴上的坐标。

\subsection{orient}

\begin{verbatim}
    record orient {
        num q1;
        num q2;
        num q3;
        num q4;
    }
\end{verbatim}

orient用于表示三维坐标系中物体的方向，或者旋转。orient必然是归一化的，即其全部成员的平方和为1。

\subsection{euler}

\begin{verbatim}
    record euler {
        num r;
        num p;
        num y;
    }
\end{verbatim}

euler用于表示三维坐标系中物体的定点旋转。旋转可以视为分三步进行：

\begin{itemize}
    \item r 首先绕z轴旋转的角度
    \item p 其次，绕新的y轴旋转的角度
    \item y 最后，绕新的x轴旋转的角度
\end{itemize}

\subsection{pose}

\begin{verbatim}
    record pose {
        pos trans;
        orient rot;
    }
\end{verbatim}

pose用于表示三维坐标系中物体的位姿，包含两个部分：

\begin{itemize}
    \item trans 物体坐标系原点相对于参考坐标系坐标原点的位移
    \item rot 物体坐标系相对于参考坐标系的旋转。
\end{itemize}

\section{内置变量}

\subsection{errno}
类型: errnum

当Tenon执行器执行遇到错误条件时，会跳转到相关函数的错误处理例程里，同时
设置内置变量errno为发生的错误的编号。错误处理例程可以用errno来判断发生
错误的种类。

\subsection{intno}
类型: intnum

当使用iconnect扩展函数连接一个中断变量到中断处理例程上时，系统会给中断变
量赋值一个中断号整数值。当该中断变量被触发时，内置变量intno会被设置为该
中断变量的值，即中断号。中断处理例程可以用intno来判断中断是由哪个中断变量
触发的。

\subsection{内置错误常量}
\vspace{-0.5em}  % 减少段前空白
以下表格列出了系统在运行时遇到错误时会抛出的错误编号及其含义。

\begin{table}[!htbp]  % [!htbp] 优化浮动体位置
\centering
\setlength{\tabcolsep}{4pt}  % 压缩列间距
\begin{tabular}{ |l|l| } 
\hline
错误编号 & 含义 \\
\hline
\verb|err_aliasio_def| & IO信号未定义 \\
\verb|err_aliasio_type| & IO信号类型不匹配 \\
\verb|err_alrdycnt| & 中断变量已连接到中断处理例程 \\
\verb|err_ao_lim| & 模拟信号超出范围 \\
\verb|err_argnotptr| & 参数不是合法引用 \\
\verb|err_argvalerr| & 参数值不合法 \\
\verb|err_divzero|  & 除零错误 \\
\verb|err_ext_function_not_implemented| & 扩展函数未实现 \\
\verb|err_fileacc| & 文件访问错误 \\
\verb|err_fileopen| & 文件打开错误 \\
\verb|err_fileexist| & 文件已存在 \\
\verb|err_go_lim| & group信号超出范围 \\
\verb|err_illraise| & 错误编号不在1-90范围 \\
\verb|err_lib_syscall| & 库函数使用错误 \\
\verb|err_maxintval| & tryint参数超最大整数值 \\
\verb|err_motion| & 控制器运动错误 \\
\verb|err_nomem| & 内存分配失败 \\
\verb|err_norununit| & 无实际信号源 \\
\verb|err_notintval| & tryint参数非整数 \\
\verb|err_notsupp| & 函数不支持当前参数 \\
\verb|err_nulldata| & 变量未初始化 \\
\verb|err_orient_unnormalized| & 四元数归一化失败 \\
\verb|err_outofbnd| & 数组下标越界 \\
\verb|err_refunkdat| & 引用不存在全局变量 \\
\verb|err_sock_addr_inuse| & socket地址被占用 \\
\verb|err_sock_closed| & socket已关闭 \\
\verb|err_sock_timeout| & socket超时 \\
\verb|err_sock_net_unreach| & 网络访问失败 \\
\verb|err_type_invalid| & 类型匹配错误 \\
\verb|err_unkino| & 引用不存在中断号 \\
\verb|err_wait_maxtime| & 超过最大等待时间 \\
\hline
\end{tabular}
\end{table}

\vspace{-1em}  % 压缩段后空白
% 后续内容自动衔接，避免单独分页

\section{内置函数}

\subsection{内置系统函数}

以下表格列出了一些常用的系统函数及其功能。

\begin{center}
\begin{tabular}{ |l|l| } 
\hline
函数 & 功能 \\
\hline
\verb|modexist| & 检查模块是否存在 \\
\verb|timestamp| & 获取系统当前的时间戳 \\
\verb|retry| & 在错误处理器中使用，重新执行引发错误的语句 \\
\verb|trynext| & 在错误处理器中使用，从引发错误的语句的下一语句开始执行，以恢复程序的正常运行 \\
\verb|exit| & 退出当前任务的执行 \\
\verb|waittime| & 暂停当前任务的执行一段时间 \\
\verb|waituntil| & 暂停，直到满足继续执行的条件或者达到最大等待时间 \\
\verb|loadtask| & 加载一个任务并执行 \\
\verb|unloadtask| & 等待一个任务的执行结束并清理该任务 \\

\hline
\end{tabular}
\end{center}

\vspace{2ex}

\noindent \textbf{modexist}\vspace{-1.5ex}

\begin{verbatim}
opaque bool modexist(string modname);
\end{verbatim}

参数：

\begin{itemize}
    \item modname 要查询否存在的模块的模块名
\end{itemize}

返回值：

模块存在时返回true；否则返回false

\vspace{2ex}

\noindent \textbf{timestamp}\vspace{-1.5ex}

\begin{verbatim}
opaque num timestamp();
\end{verbatim}

参数：

无

返回值：

返回系统当前的时间戳，精度为0.001s

\vspace{2ex}

\noindent \textbf{retry}\vspace{-1.5ex}

\begin{verbatim}
opaque void retry();
\end{verbatim}

参数：

无

返回值：

无

\vspace{2ex}

\noindent \textbf{trynext}\vspace{-1.5ex}

\begin{verbatim}
opaque void trynext();
\end{verbatim}

参数：

无

返回值：

无

\vspace{2ex}

\noindent \textbf{exit}\vspace{-1.5ex}

\begin{verbatim}
opaque void exit();
\end{verbatim}

参数：

无

返回值：

无

\vspace{2ex}

\noindent \textbf{waittime}\vspace{-1.5ex}

\begin{verbatim}
opaque void waittime(num time);
\end{verbatim}

参数：

\begin{itemize}
    \item time 当前任务暂停运行的时长，单位为s，精度为0.001s
\end{itemize}

返回值：

无

\vspace{2ex}

\noindent \textbf{waituntil}\vspace{-1.5ex}

\begin{verbatim}
opaque void waituntil(bool_t cond, num pollrate = 0.1,
                      num maxtime = 0.0, bool& timeflag = void);
\end{verbatim}

参数：

\begin{itemize}
    \item cond 继续执行的判断条件，可以是一个bool类型的表达式，
               例如 \verb|waituntil(shared_num_read(a) > 0)|
    \item pollrate 每次检查判断条件的时间间隔
    \item maxtime 最大等待时间
    \item timeflag 标记位，当等待时间超过maxtime时，如果传递了timeflag，
                   则timeflag被设置为true，否则抛出错误
\end{itemize}

返回值：

无

\vspace{2ex}

\noindent \textbf{loadtask}\vspace{-1.5ex}

\begin{verbatim}
opaque bool loadtask(string name, string bin, bool bpOnEntry = true,
                     string& libs[*] = void, num& taskid = void);
\end{verbatim}

参数：

\begin{itemize}
    \item name 要加载的任务的Tenon可执行文件的名称
    \item bin 要加载的任务的bin文件的路径
    \item bpOnEntry 是否在要加载的任务入口处设置调试断点
    \item libs 要加载的任务运行时使用的导入库的列表
    \item taskid [OUT] 使用此参数接收任务加载成功后，任务的一个标识符，用于区别任务 
\end{itemize}

返回值：

任务加载成功并开始运行，返回true；否则返回false

\vspace{2ex}

\noindent \textbf{unloadtask}\vspace{-1.5ex}

\begin{verbatim}
opaque bool unloadtask(num taskid);
\end{verbatim}

参数：

\begin{itemize}
    \item taskid 要卸载的任务的标识符，即loadtask时传入的taskid变量的值
\end{itemize}

返回值：

任务执行完毕并卸载成功，返回true；否则返回false

\vspace{2ex}
